package top.huxy.boot.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import top.huxy.boot.model.entity.ScheduleJob;
import top.huxy.boot.service.ScheduleService;
import top.huxy.boot.util.IPAddressUtils;
import top.huxy.boot.util.RequestUtils;
import top.huxy.boot.util.schedule.ScheduleUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
@Order(Integer.MIN_VALUE)
@Slf4j
public class EnvironmentCheck implements ApplicationListener<ApplicationStartedEvent> {
    private boolean envNotRight;

    @Autowired
    ScheduleService scheduleService;

    @Autowired
    ScheduleUtils scheduleUtils;

    @Override
    public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
        ConfigurableApplicationContext context = applicationStartedEvent.getApplicationContext();
        String env = context.getEnvironment().getProperty("spring.profiles.active");
        log.info("当前环境为<" + env + ">，开始环境自检");
        checkDatabaseEnvironment(context);
        checkRedisEnvironment(context);
        if (envNotRight) {
            log.error("环境自检测不通过，程序停止");
            System.exit(0);
        } else {
            log.info("环境自检测完毕");
        }

        loadAllSchedule();

        loadStaticClass();
    }

    /**
     * 有些类的静态代码块较为耗时，所以在应用启动时初始化，可节省第一次请求耗时。不然第一次请求要等2秒左右
     */
    private void loadStaticClass() {
        RequestUtils.parseOsAndBrowser("");
        IPAddressUtils.getCityInfo("127.0.0.1");
    }

    private void loadAllSchedule() {
        log.info("开始加载所有定时任务");
        List<ScheduleJob> allEnableScheduleJob = scheduleService.getAllEnableScheduleJob();
        int errorCount=0;
        for (ScheduleJob scheduleJob : allEnableScheduleJob) {
            try{
                scheduleUtils.addSchedule(scheduleJob);
            }catch (Exception e){
                log.error("定时任务加载失败",e);
                errorCount++;
            }
        }
        log.info("定时任务加载完毕，共{}个定时任务,错误{}个", allEnableScheduleJob.size(),errorCount);
    }

    private void checkDatabaseEnvironment(ConfigurableApplicationContext context) {
        DataSource dataSource = context.getBean(DataSource.class);
        try {
            Connection connection = dataSource.getConnection();
            connection.close();
        } catch (SQLException e) {
            log.error("数据库环境自检出错,请检查数据库环境", e);
            envNotRight = true;
        }
    }

    @SuppressWarnings("all")
    private void checkRedisEnvironment(ConfigurableApplicationContext app) {
        Object obj = app.getBean("redisTemplate");
        RedisTemplate<String, Object> redisTemplate = (RedisTemplate) obj;
        try {
            redisTemplate.opsForValue().set("huxy", "666", 1L, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("redis环境自检出错，请检查redis环境配置", e);
            envNotRight = true;
        }
    }
}
